package org.zergle.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 提供反射操作的一系列方法
 * 
 * @author Johnson.Lee
 */
public class Reflections {

	/**
	 * not visible
	 */
	private Reflections() {
	}

	/**
	 * 返回指定对象的属性值
	 * 
	 * @param object
	 *            目标对象
	 * @param fieldName
	 *            属性名称
	 * @return 返回目标对象指定名称的属性值
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @see #set(Object, String, Object)
	 */
	public static Object get(Object object, String fieldName)
			throws NoSuchFieldException, IllegalAccessException {
		Field field = null;
		Class<?> clazz = object.getClass();
		try {
			field = clazz.getField(fieldName);
		} catch (NoSuchFieldException e) {
			field = clazz.getDeclaredField(fieldName);
		}

		if (field != null) {
			if (!field.isAccessible()) {
				field.setAccessible(true);
			}
			return field.get(object);
		}
		return null;
	}

	/**
	 * 为指定对象设置属性值
	 * 
	 * @param object
	 *            目标对象
	 * @param fieldName
	 *            属性名称
	 * @param value
	 *            属性值
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @see #get(Object, String)
	 */
	public static void set(Object object, String fieldName, Object value)
			throws NoSuchFieldException, IllegalAccessException {
		Field field = null;
		Class<?> clazz = object.getClass();
		try {
			field = clazz.getField(fieldName);
		} catch (NoSuchFieldException e) {
			field = clazz.getDeclaredField(fieldName);
		}

		if (field != null) {
			if (!field.isAccessible()) {
				field.setAccessible(true);
			}
			field.set(object, value);
		}
	}
	
	public static Object eval(Object object, String exp) {
		return null;
	}

	/**
	 * 调用目标对象的指定方法
	 * 
	 * @param object
	 *            目标对象
	 * @param method
	 *            方法
	 * @param args
	 *            参数列表
	 * @return 返回被调用方法的返回值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static Object invoke(Object object, Method method, Object... args)
			throws IllegalArgumentException, IllegalAccessException,
			InvocationTargetException {
		if (!method.isAccessible()) {
			method.setAccessible(true);
		}
		return method.invoke(object, args);
	}

	/**
	 * 调用目标对象指定名称的方法
	 * 
	 * @param object
	 *            目标对象
	 * @param methodName
	 *            方法名称
	 * @param args
	 *            方法参数列表
	 * @return 返回被调用方法的返回值
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static Object invoke(Object object, String methodName,
			Object... args) throws SecurityException, NoSuchMethodException,
			IllegalArgumentException, IllegalAccessException,
			InvocationTargetException {
		Class<?>[] paramTypes = new Class<?>[args.length];
		for (int i = 0; i < args.length; i++) {
			paramTypes[i] = args[i].getClass();
		}
		Method method = null;
		try {
			// 先从自己定义的方法列表中查找
			method = object.getClass()
					.getDeclaredMethod(methodName, paramTypes);
		} catch (NoSuchMethodException e) {
			// 再从父类的方法列表中查找
			method = object.getClass().getMethod(methodName, paramTypes);
		}
		if (method != null) {
			if (!method.isAccessible()) {
				method.setAccessible(true);
			}
			return invoke(object, method, args);
		} else {
			throw new NoSuchMethodException(methodName);
		}
	}
}
